<template>
  <div class="components_text-clamp">
    <n-tooltip
      :content="content"
      :disabled="!isClamped"
      content-class="tooltip_text-clamp"
      :placement="placement"
    >
      <template #trigger>
        <div ref="contentEl" class="text-content" :style="contentStyle">
          {{ content }}
        </div>
      </template>
      {{ content }}
    </n-tooltip>
  </div>
</template>

<script setup lang="ts">
/**
 * 导入类型声明
 */
import type { CSSProperties } from 'vue';
import type { PopoverPlacement } from 'naive-ui';

/**
 * 定义props的类型声明
 */
interface PropType {
  content: string;
  lineHeight?: number;
  maxLines?: number;
  placement?: PopoverPlacement;
}

/**
 * 定义props
 */
const props = withDefaults(defineProps<PropType>(), {
  lineHeight: 24,
  maxLines: 1,
  placement: 'top',
});

/**
 * 监听content属性变化
 */
watch(
  () => props.content,
  () => {
    checkClamped();
  },
);

/**
 * 定义响应式数据
 */
const isClamped = ref<boolean>(false);

/**
 * 获取页面元素
 */
const contentEl = useTemplateRef<HTMLElement | null>('contentEl');

/**
 * 内容区域样式
 */
const contentStyle = computed<CSSProperties>(() => ({
  '-webkit-line-clamp': props.maxLines || 1,
  display: '-webkit-box',
  overflow: 'hidden',
  '-webkit-box-orient': 'vertical',
  lineHeight: `${props.lineHeight}px`,
}));

/**
 * 检测是否需要折叠
 */
function checkClamped(): void {
  if (!contentEl.value) {
    return;
  }
  const maxHeight = props.lineHeight * props.maxLines;
  isClamped.value = contentEl.value.scrollHeight > maxHeight;
}

/**
 * 生命周期
 */
onMounted(() => {
  checkClamped();
});
</script>

<style lang="less" scoped>
.components_text-clamp {
  position: relative;

  .text-content {
    white-space: pre-line;
    word-break: break-word;
  }
}
</style>
